infra(cpb): add dedicated role provisioning and schema setup [coderabbit-ai-review]#123
infra(cpb): add dedicated role provisioning and schema setup [coderabbit-ai-review]#123SashkoMarchuk wants to merge 9 commits intomainfrom
Conversation
…ple Bot Replace the old setup script that required postgres admin access and CREATEROLE with a version that uses temporal user (CREATEDB) and grants to existing n8n user. Add complete 6-table schema (cycles, opt_in_responses, pairings, pair_history, interactions, admin_reports) with idempotent IF NOT EXISTS, triggers, and indexes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix two filename references in header comments flagged by CodeRabbit: - setup-db.sh usage example: cpb-setup-db.sh → cpb/setup-db.sh - init-schema.sql usage example: cpb-init-schema.sql → init-schema.sql Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactor schema grant error handling from fragile `cmd && echo || { ... }`
to proper if/then/else. Prevents false error-path execution if echo fails.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace temporal-based DB setup with a two-script architecture: - create-role.sh: one-time provisioning using RDS master password to create cpb_app role and cpb_bot database - setup-db.sh: repeatable schema setup connecting as cpb_app Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🤖 CodeRabbit AI Review AvailableTo request a code review from CodeRabbit AI, add CodeRabbit will analyze your code and provide feedback on:
Note: Reviews are only performed when |
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 13 minutes and 42 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Warning CodeRabbit GitHub Action detectedThe repository is using both CodeRabbit Pro and CodeRabbit Open Source (via GitHub Actions), which is not recommended as it may lead to duplicate comments and extra noise. Please remove the CodeRabbit GitHub Action. 📝 WalkthroughWalkthroughReplaces an old CPB DB provisioning script with two new executables: Changes
Sequence Diagram(s)sequenceDiagram
participant Operator as "Operator"
participant FS as "Filesystem (repo/sql)"
participant Script as "create-role.sh"
participant PG as "Postgres master (psql)"
rect rgba(200,240,200,0.5)
Operator->>Script: invoke with env (HOST, MASTER_PW, CPB_PW)
Script->>PG: CONNECT as master (psql ON_ERROR_STOP=1)
PG-->>Script: connection OK / auth
Script->>PG: CREATE ROLE IF NOT EXISTS / ALTER ROLE ... WITH PASSWORD
PG-->>Script: role created/updated
Script->>PG: CREATE DATABASE IF NOT EXISTS ... OWNER on create
PG-->>Script: database created or exists
Script->>PG: CHECK/CHANGE DB owner if different
Script->>PG: REASSIGN OWNED BY other_roles TO cpb_role
PG-->>Script: reassignments applied
Script->>PG: GRANT CONNECT/USAGE/ALL PRIVILEGES
Script-->>Operator: provisioning complete + next steps
end
sequenceDiagram
participant Operator as "Operator"
participant FS as "Filesystem (repo/sql)"
participant Script as "setup-db.sh"
participant PG as "Postgres CPB DB (psql)"
rect rgba(200,220,255,0.5)
Operator->>Script: invoke with env (HOST, CPB_PW)
Script->>FS: locate sql/cpb/init-schema.sql
FS-->>Script: file found
Script->>PG: CONNECT and run SELECT 1 (verify)
PG-->>Script: success
Script->>PG: psql -f init-schema.sql (apply schema)
PG-->>Script: schema applied
Script->>PG: count base tables in public schema
PG-->>Operator: verified table count (expected 6) -> success banner
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/cpb/create-role.sh`:
- Around line 110-148: Step 3 in create-role.sh only changes the database owner
but leaves individual objects owned by the previous role, causing schema
reapplication in setup-db.sh to fail; after the ownership transfer block (the DO
$$ ... END $$; that uses current_owner and ${CPB_USER}) add a REASSIGN OWNED BY
<old_owner> TO "${CPB_USER}" step (or insert it in setup-db.sh before applying
sql/cpb/init-schema.sql) so that all tables, sequences, functions and triggers
owned by the previous role are reassigned to ${CPB_USER}; use the current_owner
variable value captured in the DO block (or ${MASTER_USER} if appropriate) to
build the REASSIGN OWNED command and run it as the superuser.
In `@scripts/cpb/setup-db.sh`:
- Around line 106-111: The script currently only warns when TABLE_COUNT != 6,
allowing setup-db.sh to exit 0 with an incomplete schema; update the else branch
that checks TABLE_COUNT to make the script fail fast by printing the warning to
stderr (as it already does) and then exiting with a non-zero status (e.g., exit
1) so callers detect failure—modify the block that compares TABLE_COUNT (the
existing if [[ "$TABLE_COUNT" -eq 6 ]]; then ... else ...) to add a failing exit
after the error messages.
In `@sql/cpb/init-schema.sql`:
- Around line 157-181: Add a multi-column CHECK constraint on the interactions
table to enforce valid touchpoint/action pairs (instead of independent checks)
by updating the CREATE TABLE for interactions (or via ALTER TABLE) to include a
constraint (e.g., interactions_touchpoint_action_valid) that allows only the
permitted action values for each touchpoint value; reference the touchpoint and
action columns in the constraint and enumerate the allowed combinations (for
example, actions allowed for 'opt_in' vs 'checkin' vs 'survey') so impossible
pairs like touchpoint='opt_in' with action='satisfied' are rejected.
- Around line 107-129: Add a uniqueness constraint to enforce one-pair-per-cycle
by making (cycle_id, person_a_id, person_b_id) unique on the pairings table;
update the schema for the pairings table (which already has CHECK (person_a_id <
person_b_id)) to include either a UNIQUE constraint or create a unique index
(e.g., uniq_pairings_cycle_pair) on those three columns so duplicate rows cannot
be inserted and notification/History duplication is prevented.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 3234300b-0af9-4cf8-900e-e8f827a63e62
📒 Files selected for processing (5)
.env.examplescripts/cpb-setup-db.shscripts/cpb/create-role.shscripts/cpb/setup-db.shsql/cpb/init-schema.sql
💤 Files with no reviewable changes (1)
- scripts/cpb-setup-db.sh
- Add REASSIGN OWNED step in create-role.sh to transfer object ownership (tables, sequences, functions) after database ownership transfer - Fail fast in setup-db.sh when table count != 6 (exit 1, not warning) - Add UNIQUE(cycle_id, person_a_id, person_b_id) to pairings table - Replace independent touchpoint/action CHECKs with composite constraint that enforces valid combinations (e.g. blocks opt_in + satisfied) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Currently reviewing new changes in this PR... Files selected (1)
Uplevel your code reviews with CodeRabbit ProCodeRabbit ProIf you like this project, please support us by purchasing the Pro version. The Pro version has advanced context, superior noise reduction and several proprietary improvements compared to the open source version. Moreover, CodeRabbit Pro is free for open source projects. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
sql/cpb/init-schema.sql (1)
188-207: Consider whether multiple reports per cycle are intentional.The
admin_reportstable allows multiple rows percycle_id. If only one report per cycle is expected, consider adding a uniqueness constraint.🔧 Optional: Add uniqueness if one report per cycle
CREATE INDEX IF NOT EXISTS idx_admin_reports_cycle ON admin_reports(cycle_id); + +-- Uncomment if only one report per cycle is allowed: +-- ALTER TABLE admin_reports ADD CONSTRAINT uq_admin_reports_cycle UNIQUE (cycle_id);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@sql/cpb/init-schema.sql` around lines 188 - 207, The admin_reports table currently allows multiple rows per cycle_id (index idx_admin_reports_cycle is non-unique); if the intent is one report per cycle, add a uniqueness constraint on admin_reports.cycle_id (either change the CREATE TABLE to include UNIQUE(cycle_id) or replace the non-unique index with a UNIQUE INDEX on cycle_id) so duplicate reports for the same cycle are prevented; ensure the trigger trg_admin_reports_updated_at and any existing data are compatible with the new uniqueness constraint before applying.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@sql/cpb/init-schema.sql`:
- Around line 188-207: The admin_reports table currently allows multiple rows
per cycle_id (index idx_admin_reports_cycle is non-unique); if the intent is one
report per cycle, add a uniqueness constraint on admin_reports.cycle_id (either
change the CREATE TABLE to include UNIQUE(cycle_id) or replace the non-unique
index with a UNIQUE INDEX on cycle_id) so duplicate reports for the same cycle
are prevented; ensure the trigger trg_admin_reports_updated_at and any existing
data are compatible with the new uniqueness constraint before applying.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: d419d69f-7c6d-4ebe-a407-f989e93bc8b6
📒 Files selected for processing (3)
scripts/cpb/create-role.shscripts/cpb/setup-db.shsql/cpb/init-schema.sql
🚧 Files skipped from review as they are similar to previous changes (1)
- scripts/cpb/setup-db.sh
One report per cycle is the correct invariant — enforce at DB level. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🔍 Vulnerabilities of
|
| digest | sha256:17e54ff5e9a181d1bdbf7334ce9637f9c3934d54a65427ae36a5743f46487f15 |
| vulnerabilities | |
| platform | linux/amd64 |
| size | 218 MB |
| packages | 358 |
📦 Base Image alpine:3
| also known as |
|
| digest | sha256:1c4eef651f65e2f7daee7ee785882ac164b02b78fb74503052a26dc061c90474 |
| vulnerabilities |
Description
Description
Description
Description
Description
Description
Description
Description
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
Description
Description
Description
Description
Description
Description
Description
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
Description
Description
Description
Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
Description
Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Description
|
There was a problem hiding this comment.
Files selected (5)
- .env.example (1)
- scripts/cpb-setup-db.sh (1)
- scripts/cpb/create-role.sh (1)
- scripts/cpb/setup-db.sh (1)
- sql/cpb/init-schema.sql (1)
Files not summarized due to errors (5)
- scripts/cpb/create-role.sh (diff tokens exceeds limit)
- sql/cpb/init-schema.sql (diff tokens exceeds limit)
- scripts/cpb-setup-db.sh (nothing obtained from openai)
- scripts/cpb/setup-db.sh (nothing obtained from openai)
- .env.example (nothing obtained from openai)
Files not reviewed due to errors (5)
- .env.example (no response)
- scripts/cpb/setup-db.sh (no response)
- sql/cpb/init-schema.sql (no response)
- scripts/cpb-setup-db.sh (no response)
- scripts/cpb/create-role.sh (no response)
Review comments generated (0)
- Review: 0
- LGTM: 0
Tips
Chat with
CodeRabbit Bot (@coderabbitai)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@coderabbitaiin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@coderabbitai: ignoreanywhere in the PR description to pause further reviews from the bot.
- Add updated_at + trigger to pairings table (6 mutable columns had no modification timestamp, breaking pattern of other mutable tables) - Remove 3 redundant indexes whose leading columns are already covered by UNIQUE constraints (opt_in_responses, pairings, admin_reports) - Fix misleading "-v" hint in setup-db.sh error message Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enforce YYYY-MM format via regex to prevent invalid values like '2026-13' or 'foobar' from being inserted. Flagged independently by two /ultra XL agents (D2-contrarian, V2-schema). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Files selected (2)
- scripts/cpb/setup-db.sh (1)
- sql/cpb/init-schema.sql (1)
Files not summarized due to errors (2)
- sql/cpb/init-schema.sql (diff tokens exceeds limit)
- scripts/cpb/setup-db.sh (nothing obtained from openai)
Files not reviewed due to errors (2)
- sql/cpb/init-schema.sql (no response)
- scripts/cpb/setup-db.sh (no response)
Review comments generated (0)
- Review: 0
- LGTM: 0
Tips
Chat with
CodeRabbit Bot (@coderabbitai)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@coderabbitaiin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@coderabbitai: ignoreanywhere in the PR description to pause further reviews from the bot.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/cpb/setup-db.sh (1)
78-84: Consider preserving the actual connection error for easier debugging.Redirecting stderr to
/dev/nullhides useful diagnostics (e.g., "password authentication failed" vs "database does not exist" vs "connection refused"). Capturing or displaying the actual error would help users troubleshoot faster.💡 Suggested improvement
echo "Step 1: Verifying database connection..." -if ! PGPASSWORD="${CPB_PASS}" psql -v ON_ERROR_STOP=1 \ - -h "$PGHOST" -p "$PGPORT" -U "$CPB_USER" -d "$CPB_DB" \ - -c "SELECT 1;" > /dev/null 2>&1; then +CONN_ERR=$(PGPASSWORD="${CPB_PASS}" psql -v ON_ERROR_STOP=1 \ + -h "$PGHOST" -p "$PGPORT" -U "$CPB_USER" -d "$CPB_DB" \ + -c "SELECT 1;" 2>&1 > /dev/null) || { echo "ERROR: Cannot connect to ${CPB_DB} as ${CPB_USER}" >&2 + echo " psql: ${CONN_ERR}" >&2 echo " Have you run create-role.sh first?" >&2 exit 1 -fi +} echo " Connection: OK"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/cpb/setup-db.sh` around lines 78 - 84, The connection check currently hides psql's stderr by redirecting output to /dev/null; change the check so the actual error message from psql is preserved and printed (for example by removing the "2>&1 > /dev/null" redirection or by capturing psql's stdout/stderr into a variable and echoing it on failure) when the PGPASSWORD="${CPB_PASS}" psql -v ON_ERROR_STOP=1 -h "$PGHOST" -p "$PGPORT" -U "$CPB_USER" -d "$CPB_DB" -c "SELECT 1;" command fails, so users see the real diagnostic (e.g., password auth failed, database missing, connection refused) instead of a generic error.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/cpb/setup-db.sh`:
- Around line 78-84: The connection check currently hides psql's stderr by
redirecting output to /dev/null; change the check so the actual error message
from psql is preserved and printed (for example by removing the "2>&1 >
/dev/null" redirection or by capturing psql's stdout/stderr into a variable and
echoing it on failure) when the PGPASSWORD="${CPB_PASS}" psql -v ON_ERROR_STOP=1
-h "$PGHOST" -p "$PGPORT" -U "$CPB_USER" -d "$CPB_DB" -c "SELECT 1;" command
fails, so users see the real diagnostic (e.g., password auth failed, database
missing, connection refused) instead of a generic error.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 3bffb364-e0f6-4138-a300-952e63da4614
📒 Files selected for processing (2)
scripts/cpb/setup-db.shsql/cpb/init-schema.sql
Capture and display the actual psql error on connection failure instead of suppressing it. Operators now see the real diagnostic (wrong password, host unreachable, DB missing) instead of generic "Cannot connect" message. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
✅ Actions performedReview triggered.
|
## Summary - Replace temporal-based interim DB setup with a two-script architecture using a dedicated `cpb_app` role - **`scripts/cpb/create-role.sh`** (NEW): One-time provisioning using RDS master password — creates `cpb_app` role, `cpb_bot` database, transfers ownership from `temporal` if needed, grants all privileges - **`scripts/cpb/setup-db.sh`** (REWRITTEN): Repeatable schema setup connecting as `cpb_app` — applies `init-schema.sql`, verifies all 6 tables - **`sql/cpb/init-schema.sql`** (NEW): Complete 6-table schema for CPB Slack bot (cycles, opt_in_responses, pairings, pair_history, interactions, admin_reports) - Deletes old `scripts/cpb-setup-db.sh` that required temporal user with CREATEDB - Adds `POSTGRES_PASSWORD_MASTER` to `.env.example` (commented out, one-time use) ## Operational Workflow ``` 1. Set POSTGRES_PASSWORD_MASTER, POSTGRES_PASSWORD_CPB, CPB_POSTGRES_HOST 2. Run: ./scripts/cpb/create-role.sh (creates role + database) 3. Run: ./scripts/cpb/setup-db.sh (creates schema tables) 4. Remove POSTGRES_PASSWORD_MASTER from environment ``` ## Security - Master password required via `:?` — immediate fail if unset, no fallbacks - `validate_pg_identifier()` on all SQL identifiers (regex + length check) - Single-quote escaping + `$$` rejection on passwords - `set -eo pipefail` + `ON_ERROR_STOP=1` on both scripts - No passwords in log output ## Test plan - [ ] Verify `bash -n` syntax check passes on both scripts - [ ] Run `create-role.sh` against RDS — role and database created - [ ] Run `create-role.sh` again — idempotent, no errors, password updated - [ ] Run `setup-db.sh` — all 6 tables created - [ ] Run `setup-db.sh` again — idempotent, no errors - [ ] Verify `cpb_app` owns `cpb_bot` database - [ ] Verify schema matches `init-schema.sql` (triggers, indexes, constraints) Supersedes #123 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Chores** * Reorganized PostgreSQL provisioning process into separate one-time role creation and schema initialization steps for improved setup reliability. * Updated environment variable configuration documentation with new provisioning credentials placeholder. * **New Features** * Added comprehensive database schema with tables for cycle management, user opt-in tracking, pairing records, interaction history, and administrative reporting capabilities. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>



Summary
cpb_approlescripts/cpb/create-role.sh(NEW): One-time provisioning using RDS master password — createscpb_approle,cpb_botdatabase, transfers ownership fromtemporalif needed, grants all privilegesscripts/cpb/setup-db.sh(REWRITTEN): Repeatable schema setup connecting ascpb_app— appliesinit-schema.sql, verifies all 6 tablessql/cpb/init-schema.sql(NEW): Complete 6-table schema for CPB Slack bot (cycles, opt_in_responses, pairings, pair_history, interactions, admin_reports)scripts/cpb-setup-db.shthat required temporal user with CREATEDBPOSTGRES_PASSWORD_MASTERto.env.example(commented out, one-time use)Operational Workflow
Security
:?— immediate fail if unset, no fallbacksvalidate_pg_identifier()on all SQL identifiers (regex + length check)$$rejection on passwordsset -eo pipefail+ON_ERROR_STOP=1on both scriptsTest plan
bash -nsyntax check passes on both scriptscreate-role.shagainst RDS — role and database createdcreate-role.shagain — idempotent, no errors, password updatedsetup-db.sh— all 6 tables createdsetup-db.shagain — idempotent, no errorscpb_appownscpb_botdatabaseinit-schema.sql(triggers, indexes, constraints)Supersedes #122
Summary by CodeRabbit
Chores
New Features